<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=2"><meta name="theme-color" content="#222"><meta name="generator" content="Hexo 3.9.0"><link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon.ico"><link rel="icon" type="image/png" sizes="16x16" href="/favicon.ico"><link rel="mask-icon" href="/images/logo.svg" color="#222"><meta name="baidu-site-verification" content="WIIeufYjj6"><link rel="stylesheet" href="/css/main.css"><link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css"><script id="hexo-configurations">var NexT=window.NexT||{},CONFIG={hostname:new URL("http://winddoing.github.io").hostname,root:"/",scheme:"Mist",version:"7.7.0",exturl:!1,sidebar:{position:"right",width:300,display:"post",padding:18,offset:12,onmobile:!1},copycode:{enable:!0,show_result:!1,style:"flat"},back2top:{enable:!0,sidebar:!1,scrollpercent:!1},bookmark:{enable:!1,color:"#222",save:"auto"},fancybox:!1,mediumzoom:!1,lazyload:!1,pangu:!1,comments:{style:"tabs",active:"livere",storage:!0,lazyload:!1,nav:null,activeClass:"livere"},algolia:{appID:"OWFNL0AG1F",apiKey:"796a4b50e2653330cac4e0f8b1f8ade4",indexName:"winddoing",hits:{per_page:10},labels:{input_placeholder:"输入关键词",hits_empty:"没有找到与「${query}」相关的内容",hits_stats:"${hits} 条相关记录，共耗时 ${time} ms"}},localsearch:{enable:!0,trigger:"auto",top_n_per_article:1,unescape:!1,preload:!1},path:"search.xml",motion:{enable:!0,async:!1,transition:{post_block:"fadeIn",post_header:"slideDownIn",post_body:"slideDownIn",coll_header:"slideLeftIn",sidebar:"slideUpIn"}}}</script><meta name="description" content="NEON是一种压缩的SIMD架构，主要是给多媒体使用，结果并行计算的问题。  NEON是ARMv7-A和ARMv7-R引入的特性，在后面的ARMv8-A和ARMv8-R中也扩展其功能.1288bit的向量运算      ARMv7-A/R ARMv8-A/R ARMv8-A       AArch32 AArch64   Floating-point 32-bit 16-bit*/32-bit 1"><meta name="keywords" content="SIMD"><meta property="og:type" content="article"><meta property="og:title" content="ARMv8中的SIMD运算"><meta property="og:url" content="http://winddoing.github.io/post/13631.html"><meta property="og:site_name" content="Winddoing&#39;s Blog"><meta property="og:description" content="NEON是一种压缩的SIMD架构，主要是给多媒体使用，结果并行计算的问题。  NEON是ARMv7-A和ARMv7-R引入的特性，在后面的ARMv8-A和ARMv8-R中也扩展其功能.1288bit的向量运算      ARMv7-A/R ARMv8-A/R ARMv8-A       AArch32 AArch64   Floating-point 32-bit 16-bit*/32-bit 1"><meta property="og:locale" content="zh-CN"><meta property="og:image" content="http://winddoing.github.io/images/2019/03/armv8simd寄存器.png"><meta property="og:image" content="http://winddoing.github.io/images/2019/03/armv8simd寄存器标识vx.png"><meta property="og:image" content="http://winddoing.github.io/images/2019/03/armv8simd寄存器打包.png"><meta property="og:image" content="http://winddoing.github.io/images/2019/03/armvc8.png"><meta property="og:image" content="http://winddoing.github.io/images/2019/03/armv8simd指令op.png"><meta property="og:updated_time" content="2020-07-04T09:34:15.244Z"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="ARMv8中的SIMD运算"><meta name="twitter:description" content="NEON是一种压缩的SIMD架构，主要是给多媒体使用，结果并行计算的问题。  NEON是ARMv7-A和ARMv7-R引入的特性，在后面的ARMv8-A和ARMv8-R中也扩展其功能.1288bit的向量运算      ARMv7-A/R ARMv8-A/R ARMv8-A       AArch32 AArch64   Floating-point 32-bit 16-bit*/32-bit 1"><meta name="twitter:image" content="http://winddoing.github.io/images/2019/03/armv8simd寄存器.png"><link rel="canonical" href="http://winddoing.github.io/post/13631.html"><script id="page-configurations">CONFIG.page={sidebar:"",isHome:!1,isPost:!0}</script><link rel="stylesheet" href="//cdn.jsdelivr.net/gh/theme-next/theme-next-needmoreshare2@1/needsharebutton.min.css"><style>#needsharebutton-postbottom{cursor:pointer;height:26px;margin-top:10px;position:relative}#needsharebutton-postbottom .btn{border:1px solid $btn-default-border-color;border-radius:3px;display:initial;padding:1px 4px}</style><title>ARMv8中的SIMD运算 | Winddoing's Blog</title><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?38fa95924670925239ef842cb0c8722b";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><noscript><style>.sidebar-inner,.use-motion .brand,.use-motion .collection-header,.use-motion .comments,.use-motion .menu-item,.use-motion .pagination,.use-motion .post-block,.use-motion .post-body,.use-motion .post-header{opacity:initial}.use-motion .site-subtitle,.use-motion .site-title{opacity:initial;top:initial}.use-motion .logo-line-before i{left:initial}.use-motion .logo-line-after i{right:initial}</style></noscript></head><body itemscope itemtype="http://schema.org/WebPage"><div class="container use-motion"><div class="headband"></div><header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="header-inner"><div class="site-brand-container"><div class="site-meta"><div><a href="/" class="brand" rel="start"><span class="logo-line-before"><i></i></span> <span class="site-title">Winddoing's Blog</span><span class="logo-line-after"><i></i></span></a></div><h1 class="site-subtitle" itemprop="description">Follow Excellent, Success will Chase you</h1></div><div class="site-nav-toggle"><div class="toggle" aria-label="切换导航栏"><span class="toggle-line toggle-line-first"></span><span class="toggle-line toggle-line-middle"></span><span class="toggle-line toggle-line-last"></span></div></div></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-fw fa-home"></i> 首页</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i> 标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i> 分类</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i> 归档</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-fw fa-user"></i> 关于</a></li><li class="menu-item menu-item-search"><a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i> 搜索</a></li></ul></nav><div class="site-search"><div class="popup search-popup"><div class="search-header"><span class="search-icon"><i class="fa fa-search"></i></span><div class="search-input-container"> <input autocomplete="off" autocorrect="off" autocapitalize="none" placeholder="搜索..." spellcheck="false" type="text" id="search-input"></div><span class="popup-btn-close"><i class="fa fa-times-circle"></i></span></div><div id="search-result"></div></div><div class="search-pop-overlay"></div></div></div></header><div class="back-to-top"><i class="fa fa-arrow-up"></i> <span>0%</span></div><main class="main"><div class="main-inner"><div class="content-wrap"><div class="content"><div class="posts-expand"><article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN"><link itemprop="mainEntityOfPage" href="http://winddoing.github.io/post/13631.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="image" content="/images/Winddoing.jpg"><meta itemprop="name" content="Winddoing"><meta itemprop="description" content="失败缘于忽视细处，成功始于重视小事。"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Winddoing's Blog"></span><header class="post-header"><h2 class="post-title" itemprop="name headline"> ARMv8中的SIMD运算</h2><div class="post-meta"><span class="post-meta-item"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time title="创建时间：2019-03-01 11:18:00" itemprop="dateCreated datePublished" datetime="2019-03-01T11:18:00+08:00">2019-03-01</time></span><span class="post-meta-item"><span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/ARM/" itemprop="url" rel="index"><span itemprop="name">ARM</span></a></span> ， <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/ARM/SIMD/" itemprop="url" rel="index"><span itemprop="name">SIMD</span></a></span></span><span id="/post/13631.html" class="post-meta-item leancloud_visitors" data-flag-title="ARMv8中的SIMD运算" title="阅读次数"><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数：</span><span class="leancloud-visitors-count"></span></span><span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display:none"><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">阅读次数：</span><span id="busuanzi_value_page_pv"></span></span><br><span class="post-meta-item" title="本文字数"><span class="post-meta-item-icon"><i class="fa fa-file-word-o"></i></span> <span class="post-meta-item-text">本文字数：</span> <span>8.1k</span></span><span class="post-meta-item" title="阅读时长"><span class="post-meta-item-icon"><i class="fa fa-clock-o"></i></span> <span class="post-meta-item-text">阅读时长 &asymp;</span> <span>7 分钟</span></span></div></header><div class="post-body" itemprop="articleBody"><p><code>NEON</code>是一种压缩的SIMD架构，主要是给多媒体使用，结果并行计算的问题。</p><blockquote><p>NEON是ARMv7-A和ARMv7-R引入的特性，在后面的ARMv8-A和ARMv8-R中也扩展其功能.1288bit的向量运算</p></blockquote><table><thead><tr><th style="text-align:center"></th><th style="text-align:center">ARMv7-A/R</th><th style="text-align:center">ARMv8-A/R</th><th style="text-align:center">ARMv8-A</th></tr></thead><tbody><tr><td style="text-align:center"></td><td style="text-align:center"></td><td style="text-align:center">AArch32</td><td style="text-align:center">AArch64</td></tr><tr><td style="text-align:center">Floating-point</td><td style="text-align:center">32-bit</td><td style="text-align:center">16-bit*/32-bit</td><td style="text-align:center">16-bit*/32-bit</td></tr><tr><td style="text-align:center">Integer</td><td style="text-align:center">8-bit/16-bit/32-bit</td><td style="text-align:center">8-bit/16-bit/32-bit/64-bit</td><td style="text-align:center">8-bit/16-bit/32-bit/64-bit</td></tr></tbody></table><a id="more"></a><h2 id="ARMv8与ARMv7的区别"><a href="#ARMv8与ARMv7的区别" class="headerlink" title="ARMv8与ARMv7的区别"></a>ARMv8与ARMv7的区别</h2><ul><li>1.与<code>通用寄存器</code>相同的助记符</li></ul><table><thead><tr><th style="text-align:center">CPU</th><th style="text-align:center">通用</th><th style="text-align:center">SIMD</th></tr></thead><tbody><tr><td style="text-align:center">ARMv7</td><td style="text-align:center">mul, r0, r0, r1</td><td style="text-align:center">vmul d0, d0, d1</td></tr><tr><td style="text-align:center">ARMv8</td><td style="text-align:center">mul x0, x0, x1</td><td style="text-align:center">mul v0.u8, v0.u8, v1.u8</td></tr></tbody></table><blockquote><p><strong>注意：在ARMv7中所有的SIMD汇编的操作码如<code>mul</code>的前缀都有<code>v</code>如vml</strong></p></blockquote><ul><li><p>2.ARMv8的寄存器是ARMv7的两倍</p><ul><li>ARMv8拥有<code>32</code>个128-bit寄存器</li><li>ARMv7拥有<code>16</code>个128-bit寄存器</li></ul></li><li><p>3.不同的指令语法</p></li></ul><h2 id="SIMD寄存器"><a href="#SIMD寄存器" class="headerlink" title="SIMD寄存器"></a>SIMD寄存器</h2><p><img src="/images/2019/03/armv8simd寄存器.png" alt="armv8SIMD寄存器"></p><table><thead><tr><th style="text-align:center">寄存器</th><th style="text-align:center">个数</th><th style="text-align:center">位宽</th><th style="text-align:center">数据类型</th></tr></thead><tbody><tr><td style="text-align:center">D寄存器（<code>D0-D31</code>）</td><td style="text-align:center">32个</td><td style="text-align:center">64-bit</td><td style="text-align:center">双字（double word）</td></tr><tr><td style="text-align:center">Q寄存器（<code>Q0-Q15</code>）</td><td style="text-align:center">16个</td><td style="text-align:center">128-bit</td><td style="text-align:center">四字</td></tr></tbody></table><h2 id="矢量寄存器V0-V31：包装"><a href="#矢量寄存器V0-V31：包装" class="headerlink" title="矢量寄存器V0-V31：包装"></a>矢量寄存器V0-V31：包装</h2><p><img src="/images/2019/03/armv8simd寄存器标识vx.png" alt="armv8SIMD寄存器标识vx"></p><p>打包V0-V31中的数据，方便数据操作</p><p><img src="/images/2019/03/armv8simd寄存器打包.png" alt="ARMv8SIMD寄存器打包"></p><h2 id="矢量包装"><a href="#矢量包装" class="headerlink" title="矢量包装"></a>矢量包装</h2><p><img src="/images/2019/03/armvc8.png" alt="ARMvc8"></p><p><strong>主要定义每一个矢量Vn的数据位宽</strong></p><table><thead><tr><th style="text-align:center">标识</th><th style="text-align:center">位宽</th><th style="text-align:center">数据类型</th><th style="text-align:left">示例</th></tr></thead><tbody><tr><td style="text-align:center"><code>b</code></td><td style="text-align:center">8bit</td><td style="text-align:center">char</td><td style="text-align:left">v0.8b,v0.16b: 8个bit16个bit</td></tr><tr><td style="text-align:center"><code>h</code></td><td style="text-align:center">16bit</td><td style="text-align:center">short</td><td style="text-align:left">v0.4h，v0.8h： 4或8个半字（short类型）</td></tr><tr><td style="text-align:center"><code>s</code></td><td style="text-align:center">32bit</td><td style="text-align:center">int</td><td style="text-align:left">v0.2s，v0.4s：2或4个字</td></tr><tr><td style="text-align:center"><code>d</code></td><td style="text-align:center">64bit</td><td style="text-align:center">long long</td><td style="text-align:left">v0.2d：2个double word</td></tr></tbody></table><h2 id="指令语法"><a href="#指令语法" class="headerlink" title="指令语法"></a>指令语法</h2><p><img src="/images/2019/03/armv8simd指令op.png" alt="ARMv8SIMD指令op"></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ld4 &#123;v0.4h-v3.4h&#125;, [%0]</span><br></pre></td></tr></table></figure><p>等同于：<br></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ld4 &#123;v0.4h, v1.4h, v2.4h, v3.4h&#125;, [%0]</span><br></pre></td></tr></table></figure><p></p><h2 id="内联函数编程"><a href="#内联函数编程" class="headerlink" title="内联函数编程"></a>内联函数编程</h2><p>NEON 内在函数在头文件<code>arm_neon.h</code>中定义。头文件既定义内在函数，也定义一组向量类型</p><blockquote><p><a href="http://infocenter.arm.com/help/topic/com.arm.doc.dui0348bc/DUI0348BC_rvct_comp_ref_guide.pdf" target="_blank" rel="noopener">NEON操作函数</a></p><ul><li><a href="https://raw.githubusercontent.com/EmDepTeam/arm-linux-gnueabihf/master/lib/gcc/arm-linux-gnueabihf/7.3.1/include/arm_neon.h" target="_blank" rel="noopener">arm_neon.h</a></li></ul></blockquote><h2 id="内嵌汇编编程"><a href="#内嵌汇编编程" class="headerlink" title="内嵌汇编编程"></a>内嵌汇编编程</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">asm volatile(</span><br><span class="line">    &quot;mnemonic+operand \n\t&quot;</span><br><span class="line">    &quot;mnemonic+operand \n\t&quot;</span><br><span class="line">    &quot;mnemonic+operand \n\t&quot;</span><br><span class="line"></span><br><span class="line">    : //output operand list  /*输出操作数列表*/</span><br><span class="line">    : //input operand list   /*输入操作数列表*/</span><br><span class="line">    : //Dirty registers etc  /*被改变资源列表*/</span><br><span class="line">);</span><br></pre></td></tr></table></figure><h3 id="操作符-amp-修饰符"><a href="#操作符-amp-修饰符" class="headerlink" title="操作符&amp;修饰符"></a>操作符&amp;修饰符</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">asm volatile(</span><br><span class="line">        &quot;add %0, %1, %2&quot;</span><br><span class="line"></span><br><span class="line">        : &quot;=r&quot; (ret)</span><br><span class="line">        : &quot;r&quot; (a), &quot;r&quot; (b)</span><br><span class="line">        );</span><br></pre></td></tr></table></figure><table><thead><tr><th style="text-align:center"><strong>操作符</strong></th><th style="text-align:center">含义</th></tr></thead><tbody><tr><td style="text-align:center"><code>r</code></td><td style="text-align:center">通用寄存器</td></tr><tr><td style="text-align:center"><code>m</code></td><td style="text-align:center">一个有效的内存地址</td></tr><tr><td style="text-align:center"><code>I</code></td><td style="text-align:center">数据处理中的立即数</td></tr><tr><td style="text-align:center"><code>X</code></td><td style="text-align:center">被修饰的操作符只能作为输出</td></tr></tbody></table><table><thead><tr><th style="text-align:center"><strong>修饰符</strong></th><th style="text-align:center">含义</th></tr></thead><tbody><tr><td style="text-align:center"><code>无</code></td><td style="text-align:center">只读</td></tr><tr><td style="text-align:center"><code>=</code></td><td style="text-align:center">只写</td></tr><tr><td style="text-align:center"><code>+</code></td><td style="text-align:center">可读可写</td></tr><tr><td style="text-align:center"><code>&amp;</code></td><td style="text-align:center">只能作为输出</td></tr></tbody></table><h3 id="传参"><a href="#传参" class="headerlink" title="传参"></a>传参</h3><h4 id="参数序列"><a href="#参数序列" class="headerlink" title="参数序列"></a>参数序列</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">asm volatile(</span><br><span class="line">        &quot;add %0, %1, %2&quot;</span><br><span class="line"></span><br><span class="line">        : &quot;=r&quot; (ret)</span><br><span class="line">        : &quot;r&quot; (a), &quot;r&quot; (b)</span><br><span class="line">        );</span><br></pre></td></tr></table></figure><blockquote><ul><li><code>ret</code>: <code>%0</code>, 第一个参数</li><li><code>a</code> : <code>%1</code>, 第二个参数</li><li><code>b</code> : <code>%2</code>, 第三个参数</li></ul></blockquote><h4 id="参数名"><a href="#参数名" class="headerlink" title="参数名"></a>参数名</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">asm volatile(</span><br><span class="line">        &quot;add %[result], %[a], %[b]&quot;</span><br><span class="line"></span><br><span class="line">        : [result] &quot;=r&quot; (ret)</span><br><span class="line">        : [a] &quot;r&quot; (a), [b] &quot;r&quot; (b)</span><br><span class="line">        );</span><br></pre></td></tr></table></figure><blockquote><p>传入参数不依赖参数序列</p></blockquote><h2 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h2><h3 id="4x4矩阵乘法"><a href="#4x4矩阵乘法" class="headerlink" title="4x4矩阵乘法"></a>4x4矩阵乘法</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdint.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/time.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> __aarch64__</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;arm_neon.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">dump</span><span class="params">(<span class="keyword">uint16_t</span> **x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> i, j;</span><br><span class="line">    <span class="keyword">uint16_t</span> *xx = (<span class="keyword">uint16_t</span> *)x;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"%s:\n"</span>, __func__);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; <span class="number">4</span>; i++) &#123;</span><br><span class="line">        <span class="keyword">for</span>(j = <span class="number">0</span>; j &lt; <span class="number">4</span>; j++) &#123;</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"%3d "</span>, *(xx + (i &lt;&lt; <span class="number">2</span>) + j));</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"\n"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">matrix_mul_c</span><span class="params">(<span class="keyword">uint16_t</span> aa[][<span class="number">4</span>], <span class="keyword">uint16_t</span> bb[][<span class="number">4</span>], <span class="keyword">uint16_t</span> cc[][<span class="number">4</span>])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> i = <span class="number">0</span>, j = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"===&gt; func: %s, line: %d\n"</span>, __func__, __LINE__);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; <span class="number">4</span>; i++) &#123;</span><br><span class="line">        <span class="keyword">for</span>(j = <span class="number">0</span>; j &lt; <span class="number">4</span>; j++) &#123;</span><br><span class="line">            cc[i][j] = aa[i][j] * bb[i][j];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> __aarch64__</span></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">matrix_mul_neon</span><span class="params">(<span class="keyword">uint16_t</span> **aa, <span class="keyword">uint16_t</span> **bb, <span class="keyword">uint16_t</span> **cc)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"===&gt; func: %s, line: %d\n"</span>, __func__, __LINE__);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> 1</span></span><br><span class="line">    <span class="keyword">uint16_t</span> (*a)[<span class="number">4</span>] = (<span class="keyword">uint16_t</span> (*)[<span class="number">4</span>])aa;</span><br><span class="line">    <span class="keyword">uint16_t</span> (*b)[<span class="number">4</span>] = (<span class="keyword">uint16_t</span> (*)[<span class="number">4</span>])bb;</span><br><span class="line">    <span class="keyword">uint16_t</span> (*c)[<span class="number">4</span>] = (<span class="keyword">uint16_t</span> (*)[<span class="number">4</span>])cc;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"aaaaaaaa\n"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _cc0;</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _cc1;</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _cc2;</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _cc3;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">uint16x4_t</span> _aa0 = vld1_u16((<span class="keyword">uint16_t</span>*)a[<span class="number">0</span>]);</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _aa1 = vld1_u16((<span class="keyword">uint16_t</span>*)a[<span class="number">1</span>]);</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _aa2 = vld1_u16((<span class="keyword">uint16_t</span>*)a[<span class="number">2</span>]);</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _aa3 = vld1_u16((<span class="keyword">uint16_t</span>*)a[<span class="number">3</span>]);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">uint16x4_t</span> _bb0 = vld1_u16((<span class="keyword">uint16_t</span>*)b[<span class="number">0</span>]);</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _bb1 = vld1_u16((<span class="keyword">uint16_t</span>*)b[<span class="number">1</span>]);</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _bb2 = vld1_u16((<span class="keyword">uint16_t</span>*)b[<span class="number">2</span>]);</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _bb3 = vld1_u16((<span class="keyword">uint16_t</span>*)b[<span class="number">3</span>]);</span><br><span class="line"></span><br><span class="line">    _cc0 = vmul_u16(_aa0, _bb0);</span><br><span class="line">    _cc1 = vmul_u16(_aa1, _bb1);</span><br><span class="line">    _cc2 = vmul_u16(_aa2, _bb2);</span><br><span class="line">    _cc3 = vmul_u16(_aa3, _bb3);</span><br><span class="line"></span><br><span class="line">    vst1_u16((<span class="keyword">uint16_t</span>*)c[<span class="number">0</span>], _cc0);</span><br><span class="line">    vst1_u16((<span class="keyword">uint16_t</span>*)c[<span class="number">1</span>], _cc1);</span><br><span class="line">    vst1_u16((<span class="keyword">uint16_t</span>*)c[<span class="number">2</span>], _cc2);</span><br><span class="line">    vst1_u16((<span class="keyword">uint16_t</span>*)c[<span class="number">3</span>], _cc3);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"bbbbbbbb\n"</span>);</span><br><span class="line">    <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">uint16x4_t</span> _aa[<span class="number">4</span>], _bb[<span class="number">4</span>], _cc[<span class="number">4</span>];</span><br><span class="line">    <span class="keyword">uint16_t</span> *a = (<span class="keyword">uint16_t</span>*)aa;</span><br><span class="line">    <span class="keyword">uint16_t</span> *b = (<span class="keyword">uint16_t</span>*)bb;</span><br><span class="line">    <span class="keyword">uint16_t</span> *c = (<span class="keyword">uint16_t</span>*)cc;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; <span class="number">4</span>; i++) &#123;</span><br><span class="line">        _aa[i] = vld1_u16(a + (i &lt;&lt; <span class="number">2</span>));</span><br><span class="line">        _bb[i] = vld1_u16(b + (i &lt;&lt; <span class="number">2</span>));</span><br><span class="line">        _cc[i] = vmul_u16(_aa[i], _bb[i]);</span><br><span class="line">        vst1_u16(c + (i &lt;&lt; <span class="number">2</span>), _cc[i]);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">matrix_mul_asm</span><span class="params">(<span class="keyword">uint16_t</span> **aa, <span class="keyword">uint16_t</span> **bb, <span class="keyword">uint16_t</span> **cc)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"===&gt; func: %s, line: %d\n"</span>, __func__, __LINE__);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">uint16_t</span> *a = (<span class="keyword">uint16_t</span>*)aa;</span><br><span class="line">    <span class="keyword">uint16_t</span> *b = (<span class="keyword">uint16_t</span>*)bb;</span><br><span class="line">    <span class="keyword">uint16_t</span> *c = (<span class="keyword">uint16_t</span>*)cc;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> 0</span></span><br><span class="line">    <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ldr d3, [%0, #0]           \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ldr d2, [%0, #8]           \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ldr d1, [%0, #16]          \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ldr d0, [%0, #24]          \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ldr d7, [%1, #0]           \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ldr d6, [%1, #8]           \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ldr d5, [%1, #16]          \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ldr d4, [%1, #24]          \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v3.4h, v3.4h, v7.4h    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v2.4h, v2.4h, v6.4h    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v1.4h, v1.4h, v5.4h    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v0.4h, v0.4h, v4.4h    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="comment">//"add v3.4h, v3.4h, v7.4h    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="comment">//"add v2.4h, v2.4h, v6.4h    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="comment">//"add v1.4h, v1.4h, v5.4h    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="comment">//"add v0.4h, v0.4h, v4.4h    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"str d3, [%2,#0]            \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"str d2, [%2,#8]            \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"str d1, [%2,#16]           \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"str d0, [%2,#24]           \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        : <span class="string">"+r"</span>(a),   <span class="comment">//%0</span></span></span></span><br><span class="line"><span class="function"><span class="params">          <span class="string">"+r"</span>(b),   <span class="comment">//%1</span></span></span></span><br><span class="line"><span class="function"><span class="params">          <span class="string">"+r"</span>(c)    <span class="comment">//%2</span></span></span></span><br><span class="line"><span class="function"><span class="params">        :</span></span></span><br><span class="line"><span class="function"><span class="params">        : <span class="string">"cc"</span>, <span class="string">"memory"</span>, <span class="string">"d0"</span>, <span class="string">"d1"</span>, <span class="string">"d2"</span>, <span class="string">"d3"</span>, <span class="string">"d4"</span>, <span class="string">"d5"</span>, <span class="string">"d6"</span>, <span class="string">"d7"</span></span></span></span><br><span class="line"><span class="function"><span class="params">    )</span></span>;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line">    <span class="comment">// test, OK</span></span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="comment">//"ld4 &#123;v0.4h, v1.4h, v2.4h, v3.4h&#125;, [%0] \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ld4 &#123;v0.4h-v3.4h&#125;, [%0]                \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ld4 &#123;v4.4h, v5.4h, v6.4h, v7.4h&#125;, [%1] \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v3.4h, v3.4h, v7.4h                \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v2.4h, v2.4h, v6.4h                \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v1.4h, v1.4h, v5.4h                \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v0.4h, v0.4h, v4.4h                \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"st4 &#123;v0.4h, v1.4h, v2.4h, v3.4h&#125;, [%2] \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        : <span class="string">"+r"</span>(a),   <span class="comment">//%0</span></span></span></span><br><span class="line"><span class="function"><span class="params">          <span class="string">"+r"</span>(b),   <span class="comment">//%1</span></span></span></span><br><span class="line"><span class="function"><span class="params">          <span class="string">"+r"</span>(c)    <span class="comment">//%2</span></span></span></span><br><span class="line"><span class="function"><span class="params">        :</span></span></span><br><span class="line"><span class="function"><span class="params">        : <span class="string">"cc"</span>, <span class="string">"memory"</span>, <span class="string">"v0"</span>, <span class="string">"v1"</span>, <span class="string">"v2"</span>, <span class="string">"v3"</span>, <span class="string">"v4"</span>, <span class="string">"v5"</span>, <span class="string">"v6"</span>, <span class="string">"v7"</span></span></span></span><br><span class="line"><span class="function"><span class="params">    )</span></span>;</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line">    <span class="keyword">asm</span>(<span class="string">"nop"</span>);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">const</span> <span class="keyword">char</span> *argv[])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">uint16_t</span> aa[<span class="number">4</span>][<span class="number">4</span>] = &#123;</span><br><span class="line">        &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>&#125;,</span><br><span class="line">        &#123;<span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>&#125;,</span><br><span class="line">        &#123;<span class="number">3</span>, <span class="number">6</span>, <span class="number">8</span>, <span class="number">1</span>&#125;,</span><br><span class="line">        &#123;<span class="number">2</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">1</span>&#125;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">uint16_t</span> bb[<span class="number">4</span>][<span class="number">4</span>] = &#123;</span><br><span class="line">        &#123;<span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>&#125;,</span><br><span class="line">        &#123;<span class="number">2</span>, <span class="number">4</span>, <span class="number">6</span>, <span class="number">8</span>&#125;,</span><br><span class="line">        &#123;<span class="number">2</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="number">9</span>&#125;,</span><br><span class="line">        &#123;<span class="number">5</span>, <span class="number">2</span>, <span class="number">7</span>, <span class="number">1</span>&#125;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">uint16_t</span> cc[<span class="number">4</span>][<span class="number">4</span>] = &#123;<span class="number">0</span>&#125;;</span><br><span class="line">    <span class="keyword">int</span> i, j;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">timeval</span> <span class="title">tv</span>;</span></span><br><span class="line">    <span class="keyword">long</span> <span class="keyword">long</span> start_us = <span class="number">0</span>, end_us = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    dump((<span class="keyword">uint16_t</span> **)aa);</span><br><span class="line">    dump((<span class="keyword">uint16_t</span> **)bb);</span><br><span class="line">    dump((<span class="keyword">uint16_t</span> **)cc);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ******** C **********/</span></span><br><span class="line">    gettimeofday(&amp;tv, <span class="literal">NULL</span>);</span><br><span class="line">    start_us = tv.tv_sec + tv.tv_usec;</span><br><span class="line"></span><br><span class="line">    matrix_mul_c(aa, bb, cc);</span><br><span class="line"></span><br><span class="line">    gettimeofday(&amp;tv, <span class="literal">NULL</span>);</span><br><span class="line">    end_us = tv.tv_sec + tv.tv_usec;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"aa[][]*bb[][] C time %lld us\n"</span>, end_us - start_us);</span><br><span class="line">    dump((<span class="keyword">uint16_t</span> **)cc);</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> __aarch64__</span></span><br><span class="line">    <span class="comment">/* ******** NEON **********/</span></span><br><span class="line">    <span class="built_in">memset</span>(cc, <span class="number">0</span>, <span class="keyword">sizeof</span>(<span class="keyword">uint16_t</span>) * <span class="number">4</span> * <span class="number">4</span>);</span><br><span class="line">    gettimeofday(&amp;tv, <span class="literal">NULL</span>);</span><br><span class="line">    start_us = tv.tv_sec + tv.tv_usec;</span><br><span class="line"></span><br><span class="line">    matrix_mul_neon((<span class="keyword">uint16_t</span> **)aa, (<span class="keyword">uint16_t</span> **)bb, (<span class="keyword">uint16_t</span> **)cc);</span><br><span class="line"></span><br><span class="line">    gettimeofday(&amp;tv, <span class="literal">NULL</span>);</span><br><span class="line">    end_us = tv.tv_sec + tv.tv_usec;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"aa[][]*bb[][] neon time %lld us\n"</span>, end_us - start_us);</span><br><span class="line">    dump((<span class="keyword">uint16_t</span> **)cc);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* ******** asm **********/</span></span><br><span class="line">    <span class="built_in">memset</span>(cc, <span class="number">0</span>, <span class="keyword">sizeof</span>(<span class="keyword">uint16_t</span>) * <span class="number">4</span> * <span class="number">4</span>);</span><br><span class="line">    gettimeofday(&amp;tv, <span class="literal">NULL</span>);</span><br><span class="line">    start_us = tv.tv_sec + tv.tv_usec;</span><br><span class="line"></span><br><span class="line">    matrix_mul_asm((<span class="keyword">uint16_t</span> **)aa, (<span class="keyword">uint16_t</span> **)bb, (<span class="keyword">uint16_t</span> **)cc);</span><br><span class="line"></span><br><span class="line">    gettimeofday(&amp;tv, <span class="literal">NULL</span>);</span><br><span class="line">    end_us = tv.tv_sec + tv.tv_usec;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"aa[][]*bb[][] asm time %lld us\n"</span>, end_us - start_us);</span><br><span class="line">    dump((<span class="keyword">uint16_t</span> **)cc);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">aarch64-linux-gcc -O3  matrix_4x4_mul.c</span><br></pre></td></tr></table></figure><blockquote><p>gcc –march=armv8-a [input file] -o [output file]</p></blockquote><h3 id="8x8矩阵乘法"><a href="#8x8矩阵乘法" class="headerlink" title="8x8矩阵乘法"></a>8x8矩阵乘法</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">matrix_mul_asm</span><span class="params">(<span class="keyword">uint16_t</span> **aa, <span class="keyword">uint16_t</span> **bb, <span class="keyword">uint16_t</span> **cc)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"===&gt; func: %s, line: %d\n"</span>, __func__, __LINE__);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">uint16_t</span> *a = (<span class="keyword">uint16_t</span>*)aa;</span><br><span class="line">    <span class="keyword">uint16_t</span> *b = (<span class="keyword">uint16_t</span>*)bb;</span><br><span class="line">    <span class="keyword">uint16_t</span> *c = (<span class="keyword">uint16_t</span>*)cc;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ld4 &#123;v0.8h, v1.8h, v2.8h, v3.8h&#125;, [%0]     \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ld4 &#123;v8.8h, v9.8h, v10.8h, v11.8h&#125;, [%1]   \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v0.8h, v0.8h, v8.8h                    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v1.8h, v1.8h, v9.8h                    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v2.8h, v2.8h, v10.8h                   \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v3.8h, v3.8h, v11.8h                   \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"st4 &#123;v0.8h, v1.8h, v2.8h, v3.8h&#125;, [%2]     \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"add x1, %0, #64                            \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"add x2, %1, #64                            \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"add x3, %2, #64                            \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="comment">//"ld4 &#123;v4.8h-v7.8h&#125;, [x1]                    \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ld4 &#123;v4.8h, v5.8h, v6.8h, v7.8h&#125;, [x1]     \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"ld4 &#123;v12.8h, v13.8h, v14.8h, v15.8h&#125;, [x2] \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v4.8h, v4.8h, v12.8h                   \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v5.8h, v5.8h, v13.8h                   \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v6.8h, v6.8h, v14.8h                   \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"mul v7.8h, v7.8h, v15.8h                   \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        <span class="string">"st4 &#123;v4.8h, v5.8h, v6.8h, v7.8h&#125;, [x3]     \n\t"</span></span></span></span><br><span class="line"><span class="function"><span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">        : <span class="string">"+r"</span>(a),   <span class="comment">//%0</span></span></span></span><br><span class="line"><span class="function"><span class="params">          <span class="string">"+r"</span>(b),   <span class="comment">//%1</span></span></span></span><br><span class="line"><span class="function"><span class="params">          <span class="string">"+r"</span>(c)    <span class="comment">//%2</span></span></span></span><br><span class="line"><span class="function"><span class="params">        :</span></span></span><br><span class="line"><span class="function"><span class="params">        : <span class="string">"cc"</span>, <span class="string">"memory"</span>, <span class="string">"x1"</span>, <span class="string">"x2"</span>, <span class="string">"x3"</span>, <span class="string">"v0"</span>, <span class="string">"v1"</span>, <span class="string">"v2"</span>, <span class="string">"v3"</span>, <span class="string">"v4"</span>, <span class="string">"v5"</span>, <span class="string">"v6"</span>, <span class="string">"v7"</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">            <span class="string">"v8"</span>, <span class="string">"v9"</span>, <span class="string">"v10"</span>, <span class="string">"v11"</span>, <span class="string">"v12"</span>, <span class="string">"v13"</span>, <span class="string">"v14"</span>, <span class="string">"v15"</span></span></span></span><br><span class="line"><span class="function"><span class="params">      )</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><blockquote><p>内嵌汇编实现方式<code>8x8</code></p></blockquote><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://www.uio.no/studier/emner/matnat/ifi/INF5063/h16/pensumliste/armv8-neon-programming.pdf" target="_blank" rel="noopener">ARMv8 Neon Programming</a></li><li><a href="http://infocenter.arm.com/help/topic/com.arm.doc.dht0002a/DHT0002A_introducing_neon.pdf" target="_blank" rel="noopener">Introducing NEON</a></li><li><a href="https://community.arm.com/processors/b/blog/posts/coding-for-neon---part-1-load-and-stores" target="_blank" rel="noopener">Coding for NEON - Part 1: Load and Stores</a></li><li><a href="https://community.arm.com/processors/b/blog/posts/coding-for-neon---part-2-dealing-with-leftovers" target="_blank" rel="noopener">Coding for NEON - Part 2: Dealing With Leftovers</a></li><li><a href="https://community.arm.com/processors/b/blog/posts/coding-for-neon---part-3-matrix-multiplication" target="_blank" rel="noopener">Coding for NEON - Part 3: Matrix Multiplication</a></li><li><a href="https://community.arm.com/processors/b/blog/posts/coding-for-neon---part-4-shifting-left-and-right" target="_blank" rel="noopener">Coding for NEON - Part 4: Shifting Left and Right</a></li><li><a href="https://community.arm.com/processors/b/blog/posts/coding-for-neon---part-5-rearranging-vectors" target="_blank" rel="noopener">Coding for NEON - Part 5: Rearranging Vectors</a></li><li><a href="http://infocenter.arm.com/help/topic/com.arm.doc.100095_0003_06_en/cortex_a72_mpcore_trm_100095_0003_06_en.pdf" target="_blank" rel="noopener">ARM® Cortex®-A72 MPCore Processor Technical Reference Manual</a></li></ul></div><div class="popular-posts-header">相关文章</div><ul class="popular-posts"><li class="popular-posts-item"><div class="popular-posts-title"><a href="/post/50180.html" rel="bookmark">X86平台下的SIMD运算</a></div></li><li class="popular-posts-item"><div class="popular-posts-title"><a href="/post/40199.html" rel="bookmark">AVX VMOVDQA slower than two SSE MOVDQA?</a></div></li></ul><div class="post-widgets"><div id="needsharebutton-postbottom"><span class="btn"><i class="fa fa-share-alt" aria-hidden="true"></i></span></div></div><div><div style="text-align:center;color:#ccc;font-size:14px">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div><div style="text-align:center;color:#ccc;font-size:16px"><script type="text/javascript" src="https://api.imjad.cn/hitokoto/?cat=&charset=utf-8&length=50&encode=js&fun=sync&source="></script><div id="hitokoto"><script>hitokoto()</script></div></div><div class="reward-container"><div></div> <button disable="enable" onclick="var qr = document.getElementById(&quot;qr&quot;); qr.style.display = (qr.style.display === 'none') ? 'block' : 'none';"> 打赏</button><div id="qr" style="display:none"><div style="display:inline-block"> <img src="/images/alipay.jpg" alt="Winddoing 支付宝"><p>支付宝</p></div></div></div><div><ul class="post-copyright"><li class="post-copyright-author"> <strong>本文作者：</strong> Winddoing</li><li class="post-copyright-link"> <strong>本文链接：</strong> <a href="http://winddoing.github.io/post/13631.html" title="ARMv8中的SIMD运算">http://winddoing.github.io/post/13631.html</a></li><li class="post-copyright-statement"> <strong>作者声明：</strong> 本博文为个人笔记, 由于个人能力有限，难免出现错误，欢迎大家批评指正。</li><li class="post-copyright-license"> <strong>版权声明：</strong> 本博客所有文章除特别声明外，均采用<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fa fa-fw fa-creative-commons"></i> BY-NC-SA</a> 许可协议。转载请注明出处！</li></ul></div><footer class="post-footer"><div class="post-tags"><a href="/tags/SIMD/" rel="tag"><i class="fa fa-tag"></i> SIMD</a></div><div class="post-nav"><div class="post-nav-item"><a href="/post/7190.html" rel="prev" title="ARMv8-aarch64寄存器和指令集"><i class="fa fa-chevron-left"></i> ARMv8-aarch64寄存器和指令集</a></div><div class="post-nav-item"> <a href="/post/5543.html" rel="next" title="ARM64基本的汇编语法">ARM64基本的汇编语法<i class="fa fa-chevron-right"></i></a></div></div></footer></div></article></div></div><div class="comments"><div id="lv-container" data-id="city" data-uid="MTAyMC8yOTM5OC81OTY2"></div></div><script>
  window.addEventListener('tabs:register', () => {
    let activeClass = CONFIG.comments.activeClass;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script></div><div class="toggle sidebar-toggle"><span class="toggle-line toggle-line-first"></span><span class="toggle-line toggle-line-middle"></span><span class="toggle-line toggle-line-last"></span></div><aside class="sidebar"><div class="sidebar-inner"><ul class="sidebar-nav motion-element"><li class="sidebar-nav-toc"> 文章目录</li><li class="sidebar-nav-overview"> 站点概览</li></ul><div class="post-toc-wrap sidebar-panel"><div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#ARMv8与ARMv7的区别"><span class="nav-number">1.</span> <span class="nav-text">ARMv8与ARMv7的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#SIMD寄存器"><span class="nav-number">2.</span> <span class="nav-text">SIMD寄存器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#矢量寄存器V0-V31：包装"><span class="nav-number">3.</span> <span class="nav-text">矢量寄存器V0-V31：包装</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#矢量包装"><span class="nav-number">4.</span> <span class="nav-text">矢量包装</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#指令语法"><span class="nav-number">5.</span> <span class="nav-text">指令语法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#内联函数编程"><span class="nav-number">6.</span> <span class="nav-text">内联函数编程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#内嵌汇编编程"><span class="nav-number">7.</span> <span class="nav-text">内嵌汇编编程</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#操作符-amp-修饰符"><span class="nav-number">7.1.</span> <span class="nav-text">操作符&amp;修饰符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#传参"><span class="nav-number">7.2.</span> <span class="nav-text">传参</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#参数序列"><span class="nav-number">7.2.1.</span> <span class="nav-text">参数序列</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#参数名"><span class="nav-number">7.2.2.</span> <span class="nav-text">参数名</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#示例"><span class="nav-number">8.</span> <span class="nav-text">示例</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#4x4矩阵乘法"><span class="nav-number">8.1.</span> <span class="nav-text">4x4矩阵乘法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#8x8矩阵乘法"><span class="nav-number">8.2.</span> <span class="nav-text">8x8矩阵乘法</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#参考"><span class="nav-number">9.</span> <span class="nav-text">参考</span></a></li></ol></div></div><div class="site-overview-wrap sidebar-panel"><div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person"> <img class="site-author-image" itemprop="image" alt="Winddoing" src="/images/Winddoing.jpg"><p class="site-author-name" itemprop="name">Winddoing</p><div class="site-description" itemprop="description">失败缘于忽视细处，成功始于重视小事。</div></div><div class="site-state-wrap motion-element"><nav class="site-state"><div class="site-state-item site-state-posts"> <a href="/archives/"><span class="site-state-item-count">248</span> <span class="site-state-item-name">日志</span></a></div><div class="site-state-item site-state-categories"> <a href="/categories/"><span class="site-state-item-count">57</span> <span class="site-state-item-name">分类</span></a></div><div class="site-state-item site-state-tags"> <a href="/tags/"><span class="site-state-item-count">214</span> <span class="site-state-item-name">标签</span></a></div></nav></div><div class="links-of-author motion-element"><span class="links-of-author-item"><a href="https://github.com/Winddoing" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;Winddoing" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i> GitHub</a></span><span class="links-of-author-item"><a href="https://gitee.com/winddoing" title="Gitee → https:&#x2F;&#x2F;gitee.com&#x2F;winddoing" rel="noopener" target="_blank"><i class="fa fa-fw fa-codiepie"></i> Gitee</a></span><span class="links-of-author-item"><a href="mailto:winddoing@sina.cn" title="E-Mail → mailto:winddoing@sina.cn" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i> E-Mail</a></span><span class="links-of-author-item"><a href="https://stackoverflow.com/users/9567361/winddoing" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;users&#x2F;9567361&#x2F;winddoing" rel="noopener" target="_blank"><i class="fa fa-fw fa-stack-overflow"></i> StackOverflow</a></span><span class="links-of-author-item"><a href="https://travis-ci.org/Winddoing/Winddoing.github.io" title="Travis CI → https:&#x2F;&#x2F;travis-ci.org&#x2F;Winddoing&#x2F;Winddoing.github.io" rel="noopener" target="_blank"><i class="fa fa-fw fa-terminal"></i> Travis CI</a></span></div><div class="cc-license motion-element" itemprop="license"> <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a></div><div class="links-of-blogroll motion-element"><div class="links-of-blogroll-title"><i class="fa fa-fw fa-link"></i> Links</div><ul class="links-of-blogroll-list"><li class="links-of-blogroll-item"> <a href="https://winddoing.gitbooks.io/embedded_notes/content/" title="https:&#x2F;&#x2F;winddoing.gitbooks.io&#x2F;embedded_notes&#x2F;content&#x2F;" rel="noopener" target="_blank">嵌入式相关</a></li><li class="links-of-blogroll-item"> <a href="http://blog.csdn.net/sdreamq" title="http:&#x2F;&#x2F;blog.csdn.net&#x2F;sdreamq" rel="noopener" target="_blank">CSDN</a></li><li class="links-of-blogroll-item"> <a href="http://www.wowotech.net/" title="http:&#x2F;&#x2F;www.wowotech.net&#x2F;" rel="noopener" target="_blank">蜗窝科技</a></li><li class="links-of-blogroll-item"> <a href="https://blog.csdn.net/xiongxianze" title="https:&#x2F;&#x2F;blog.csdn.net&#x2F;xiongxianze" rel="noopener" target="_blank">xiongxianze</a></li></ul></div><div id="days"></div><script>function show_date_time(){window.setTimeout("show_date_time()",1e3),BirthDay=new Date("02/26/2014 15:00:00"),today=new Date,timeold=today.getTime()-BirthDay.getTime(),sectimeold=timeold/1e3,secondsold=Math.floor(sectimeold),msPerDay=864e5,e_daysold=timeold/msPerDay,daysold=Math.floor(e_daysold),e_hrsold=24*(e_daysold-daysold),hrsold=setzero(Math.floor(e_hrsold)),e_minsold=60*(e_hrsold-hrsold),minsold=setzero(Math.floor(60*(e_hrsold-hrsold))),seconds=setzero(Math.floor(60*(e_minsold-minsold))),document.getElementById("days").innerHTML="已运行"+daysold+"天"+hrsold+"小时"+minsold+"分"+seconds+"秒"}function setzero(e){return e<10&&(e="0"+e),e}show_date_time()</script></div></div></aside><div id="sidebar-dimmer"></div></div></main><footer class="footer"><div class="footer-inner"><div class="copyright"> &copy; 2014 – <span itemprop="copyrightYear">2020</span><span class="with-love" id="heart"><i class="fa fa-heartbeat"></i></span> <span class="author" itemprop="copyrightHolder">Winddoing</span> <span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-area-chart"></i></span> <span title="站点总字数">652k</span> <span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-coffee"></i></span> <span title="站点阅读时长">9:53</span></div><div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> 强力驱动 v3.9.0</div> <span class="post-meta-divider">|</span><div class="theme-info">主题 – <a href="https://mist.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Mist</a> v7.7.0</div><div class="busuanzi-count"><script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span class="post-meta-item" id="busuanzi_container_site_uv" style="display:none"><span class="post-meta-item-icon"><i class="fa fa-user"></i></span><span class="site-uv" title="总访客量"><span id="busuanzi_value_site_uv"></span></span></span> <span class="post-meta-divider">|</span><span class="post-meta-item" id="busuanzi_container_site_pv" style="display:none"><span class="post-meta-item-icon"><i class="fa fa-eye"></i></span><span class="site-pv" title="总访问量"><span id="busuanzi_value_site_pv"></span></span></span></div><div style="display:inline"><script type="text/javascript">var cnzz_protocol="https:"==document.location.protocol?" https://":" http://";document.write(unescape("%3Cspan id='cnzz_stat_icon_1254703532'%3E%3C/span%3E%3Cscript src='"+cnzz_protocol+"s95.cnzz.com/z_stat.php%3Fid%3D1254703532%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"))</script></div><script>
  function leancloudSelector(url) {
    url = encodeURI(url);
    return document.getElementById(url).querySelector('.leancloud-visitors-count');
  }
  if (CONFIG.page.isPost) {
    function addCount(Counter) {
      var visitors = document.querySelector('.leancloud_visitors');
      var url = decodeURI(visitors.getAttribute('id'));
      var title = visitors.getAttribute('data-flag-title');

      Counter('get', `/classes/Counter?where=${JSON.stringify({ url })}`)
        .then(response => response.json())
        .then(({ results }) => {
          if (results.length > 0) {
            var counter = results[0];
            Counter('put', '/classes/Counter/' + counter.objectId, { time: { '__op': 'Increment', 'amount': 1 } })
              .then(response => response.json())
              .then(() => {
                leancloudSelector(url).innerText = counter.time + 1;
              })
              .catch(error => {
                console.error('Failed to save visitor count', error);
              })
          } else {
              Counter('post', '/classes/Counter', { title: title, url: url, time: 1 })
                .then(response => response.json())
                .then(() => {
                  leancloudSelector(url).innerText = 1;
                })
                .catch(error => {
                  console.error('Failed to create', error);
                });
          }
        })
        .catch(error => {
          console.error('LeanCloud Counter Error', error);
        });
    }
  } else {
    function showTime(Counter) {
      var visitors = document.querySelectorAll('.leancloud_visitors');
      var entries = [...visitors].map(element => {
        return decodeURI(element.getAttribute('id'));
      });

      Counter('get', `/classes/Counter?where=${JSON.stringify({ url: { '$in': entries } })}`)
        .then(response => response.json())
        .then(({ results }) => {
          if (results.length === 0) {
            document.querySelectorAll('.leancloud_visitors .leancloud-visitors-count').forEach(element => {
              element.innerText = 0;
            });
            return;
          }
          for (let item of results) {
            let { url, time } = item;
            leancloudSelector(url).innerText = time;
          }
          for (let url of entries) {
            var element = leancloudSelector(url);
            if (element.innerText == '') {
              element.innerText = 0;
            }
          }
        })
        .catch(error => {
          console.error('LeanCloud Counter Error', error);
        });
    }
  }

  fetch('https://app-router.leancloud.cn/2/route?appId=Q8qpjA3fOO7FEUBqcmcQFptF-gzGzoHsz')
    .then(response => response.json())
    .then(({ api_server }) => {
      var Counter = (method, url, data) => {
        return fetch(`https://${api_server}/1.1${url}`, {
          method: method,
          headers: {
            'X-LC-Id': 'Q8qpjA3fOO7FEUBqcmcQFptF-gzGzoHsz',
            'X-LC-Key': 'tgUTq5bX3fVmn916EMRe65eJ',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data)
        });
      };
      if (CONFIG.page.isPost) {
        if (CONFIG.hostname !== location.hostname) return;
        addCount(Counter);
      } else if (document.querySelectorAll('.post-title-link').length >= 1) {
        showTime(Counter);
      }
    });
  </script></div></footer></div><script src="/lib/anime.min.js"></script><script src="/lib/velocity/velocity.min.js"></script><script src="/lib/velocity/velocity.ui.min.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script><script>!function(){var t=document.createElement("script"),e=window.location.protocol.split(":")[0];t.src="https"===e?"https://zz.bdstatic.com/linksubmit/push.js":"http://push.zhanzhang.baidu.com/push.js";var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}()</script><script src="/js/local-search.js"></script><script>
if (document.querySelectorAll('pre.mermaid').length) {
  NexT.utils.getScript('//cdn.jsdelivr.net/npm/mermaid@8/dist/mermaid.min.js', () => {
    mermaid.initialize({
      theme: 'forest',
      logLevel: 3,
      flowchart: { curve: 'linear' },
      gantt: { axisFormat: '%m/%d/%Y' },
      sequence: { actorMargin: 50 }
    });
  }, window.mermaid);
}
</script><script src="//cdn.jsdelivr.net/gh/theme-next/theme-next-needmoreshare2@1/needsharebutton.min.js"></script><script>pbOptions={iconStyle:"default",boxForm:"horizontal",position:"bottomCenter",networks:"Weibo,Wechat,QQZone,Twitter,Facebook,Evernote"},new needShareButton("#needsharebutton-postbottom",pbOptions)</script><script>
NexT.utils.loadComments(document.querySelector('#lv-container'), () => {
  window.livereOptions = {
    refer: location.pathname.replace(CONFIG.root, '').replace('index.html', '')
  };
  (function(d, s) {
    var j, e = d.getElementsByTagName(s)[0];
    if (typeof LivereTower === 'function') { return; }
    j = d.createElement(s);
    j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
    j.async = true;
    e.parentNode.insertBefore(j, e);
  })(document, 'script');
});
</script></body></html>